import poplib
from email.parser import Parser
from email.header import decode_header
from email.utils import parseaddr

def get_email_content():
    '''返回邮箱中的最新邮件'''
    useraccount = 'my_email_liao@sina.com'
    password = '05b359f59b2efd78'
    pop3_server = 'pop.sina.com'
    # 开始连接到服务器
    server = poplib.POP3(pop3_server)
    # 打开或者关闭调试信息，为打开，会在控制台打印客户端与服务器的交互信息
    server.set_debuglevel(1)
    # 打印POP3服务器的欢迎文字，验证是否正确连接到了邮件服务器
    print(server.getwelcome().decode('utf8'))
    # 开始进行身份验证
    server.user(useraccount)
    server.pass_(password)
    # 返回邮件总数目和占用服务器的空间大小（字节数）， 通过stat()方法即可
    # email_num, email_size = server.stat()
    # print("消息的数量: {0}, 消息的总大小: {1}".format(email_num, email_size))

    # 使用list()返回所有邮件的编号，默认为字节类型的串
    rsp, msg_list, rsp_siz = server.list()
    # print("服务器的响应: {0},\n消息列表： {1},\n返回消息的大小： {2}".format(rsp, msg_list, rsp_siz))

    print('邮件总数： {}'.format(len(msg_list)))

    # 下面单纯获取最新的一封邮件
    total_mail_numbers = len(msg_list)
    rsp, msglines, msgsiz = server.retr(total_mail_numbers)
    # print("服务器的响应: {0},\n原始邮件内容： {1},\n该封邮件所占字节大小： {2}".format(rsp, msglines, msgsiz))

    msg_content = b'\r\n'.join(msglines).decode('gbk')
    msg = Parser().parsestr(text=msg_content)
    # print('解码后的邮件信息:\n{}'.format(msg))
    # 关闭与服务器的连接，释放资源
    server.close()
    return msg

def parser_subject(msg):
    '''解析邮件主题'''
    subject = msg['Subject']
    value, charset = decode_header(subject)[0]
    if charset:
        value = value.decode(charset)
    print('邮件主题： {0}'.format(value))
    return value

def parser_address(msg):
    '''解析邮件来源'''
    hdr, addr = parseaddr(msg['From'])
    # name 发送人邮箱名称， addr 发送人邮箱地址
    name, charset = decode_header(hdr)[0]
    if charset:
        name = name.decode(charset)
    print('发送人邮箱名称: {0}，发送人邮箱地址: {1}'.format(name, addr))

def guess_charset(msg):
    '''文本邮件的内容也是 str，还需要检测编码，否则，非 UTF-8 编码的邮件都无法正常显示'''
    charset = msg.get_charset()
    if charset is None:
        content_type = msg.get('Content-Type', '').lower()
        pos = content_type.find('charset=')
        if pos >= 0:
            charset = content_type[pos + 8:].strip()
    return charset

def parser_content(msg, indent=0):
    '''
    解析邮件内容
    Message 对象本身可能是一个 MIMEMultipart 对象，即包含嵌套的其他 MIMEBase 对象，嵌套可能还不止一层
    要递归地打印出 Message 对象的层次结构
    msg：邮件内容
    indent：缩进
    '''
    if msg.is_multipart(): # 有多个部分，对每个部分都进行解析
        parts = msg.get_payload()
        for n, part in enumerate(parts):
            print(f"{' ' * indent * 4} 第 {n+1} 部分")
            print(f"{' ' * indent * 4} ------------------------")
            parser_content(part, indent + 1)
    else:
        content_type = msg.get_content_type()
        if content_type == 'text/plain' or content_type == 'text/html':
            content = msg.get_payload(decode=True)
            charset = guess_charset(msg)
            if charset:
                content = content.decode(charset)
            print(f"{' ' * indent * 4} 邮件内容：{content}")
        else:
            print(f"{' ' * indent * 4} 附件内容：{content_type}")

def main():
    msg = get_email_content()
    parser_subject(msg)
    parser_address(msg)
    parser_content(msg)

if __name__ == '__main__':
    main()